import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.util.ArrayList;
import java.util.List;

public class DynamicPartitionPanel extends JPanel {
    // 内存分区定义
    static class Partition {
        int start;      // 起始地址
        int size;       // 分区大小（KB）
        boolean isFree; // 是否空闲

        public Partition(int start, int size, boolean isFree) {
            this.start = start;
            this.size = size;
            this.isFree = isFree;
        }
    }

    private List<Partition> partitions = new ArrayList<>(); // 可用分区表
    private JTextArea logArea;     // 日志输出区域
    private JComboBox<String> algorithmComboBox; // 算法选择下拉框
    private JTextField sizeField;  // 内存请求输入框
    private JPanel memoryVisualizationPanel; // 内存可视化面板

    public DynamicPartitionPanel() {
        setLayout(new BorderLayout());
        initMemory();
        initUI();
    }

    // 初始化内存（总内存1024KB）
    private void initMemory() {
        partitions.clear();
        partitions.add(new Partition(0, 1024, true));
        partitions.clear();
        partitions.add(new Partition(0, 244, true));
        partitions.add(new Partition(244, 130, false));
        partitions.add(new Partition(374, 200, true));
        partitions.add(new Partition(574, 200, false));
        partitions.add(new Partition(774, 300, true));

    }

    // 初始化界面组件
    private void initUI() {
        // 输入面板
        JPanel inputPanel = new JPanel();
        JLabel sizeLabel = new JLabel("请求内存大小 (KB):");
        sizeField = new JTextField(8);
        JButton allocateButton = new JButton("分配");
        JButton freeButton = new JButton("释放");
        algorithmComboBox = new JComboBox<>(new String[]{"最先适应", "最佳适应", "最坏适应"});

        // 内存可视化面板（用颜色块表示分区状态）
        memoryVisualizationPanel = new JPanel() {
            @Override
            protected void paintComponent(Graphics g) {
                super.paintComponent(g);
                int width = getWidth();
                int totalMemory = 1024;
                for (Partition p : partitions) {
                    int blockWidth = (int) (width * (p.size / 1024.0));
                    g.setColor(p.isFree ? Color.GREEN : Color.RED);
                    g.fillRect(p.start * width / 1024, 20, blockWidth, 30);
                    g.setColor(Color.BLACK);
                    g.drawString(p.size + "KB", p.start * width / 1024 + 5, 40);
                }
            }
        };
        memoryVisualizationPanel.setPreferredSize(new Dimension(600, 60));

        // 分配按钮事件
        allocateButton.addActionListener((ActionEvent e) -> {
            try {
                int size = Integer.parseInt(sizeField.getText());
                allocateMemory(size);
            } catch (NumberFormatException ex) {
                logArea.append("错误：请输入有效的数字！\n");
            }
        });

        // 释放按钮事件
        freeButton.addActionListener((ActionEvent e) -> {
            try {
                int start = Integer.parseInt(sizeField.getText());
                freeMemory(start);
            } catch (NumberFormatException ex) {
                logArea.append("错误：请输入有效的起始地址！\n");
            }
        });

        // 日志区域
        logArea = new JTextArea(10, 40);
        logArea.setEditable(false);

        // 布局
        inputPanel.add(sizeLabel);
        inputPanel.add(sizeField);
        inputPanel.add(new JLabel("算法选择:"));
        inputPanel.add(algorithmComboBox);
        inputPanel.add(allocateButton);
        inputPanel.add(freeButton);

        add(inputPanel, BorderLayout.NORTH);
        add(new JScrollPane(memoryVisualizationPanel), BorderLayout.CENTER);
        add(new JScrollPane(logArea), BorderLayout.SOUTH);
    }

    // 分配内存（核心逻辑）
    private void allocateMemory(int size) {
        String algorithm = (String) algorithmComboBox.getSelectedItem();
        boolean success = false;
        switch (algorithm) {
            case "最先适应":
                success = allocateFirstFit(size);
                break;
            case "最佳适应":
                success = allocateBestFit(size);
                break;
            case "最坏适应":
                success = allocateWorstFit(size);
                break;
        }
        if (success) {
            logArea.append("分配成功！当前分区状态:\n" + getPartitionStatus());
            memoryVisualizationPanel.repaint();
        } else {
            logArea.append("分配失败，无足够空间！\n");
        }
    }

    // 最先适应算法
    private boolean allocateFirstFit(int size) {
        for (Partition p : partitions) {
            if (p.isFree && p.size >= size) {
                splitPartition(p, size);
                return true;
            }
        }
        return false;
    }

    // 最佳适应算法
    private boolean allocateBestFit(int size) {
        Partition best = null;
        for (Partition p : partitions) {
            if (p.isFree && p.size >= size) {
                if (best == null || p.size < best.size) {
                    best = p;
                }
            }
        }
        if (best != null) {
            splitPartition(best, size);
            return true;
        }
        return false;
    }

    // 最坏适应算法
    private boolean allocateWorstFit(int size) {
        Partition worst = null;
        for (Partition p : partitions) {
            if (p.isFree && p.size >= size) {
                if (worst == null || p.size > worst.size) {
                    worst = p;
                }
            }
        }
        if (worst != null) {
            splitPartition(worst, size);
            return true;
        }
        return false;
    }

    // 拆分分区（分配后更新可用分区表）
    private void splitPartition(Partition p, int size) {
        p.isFree = false;
        if (p.size > size) {
            Partition newPart = new Partition(p.start + size, p.size - size, true);
            partitions.add(partitions.indexOf(p) + 1, newPart);
            p.size = size;
        }
    }

    // 释放内存
    private void freeMemory(int start) {
        for (Partition p : partitions) {
            if (p.start == start && !p.isFree) {
                p.isFree = true;
                mergeFreePartitions();
                logArea.append("释放成功！当前分区状态:\n" + getPartitionStatus());
                memoryVisualizationPanel.repaint();
                return;
            }
        }
        logArea.append("释放失败，未找到该分区！\n");
    }

    // 合并相邻空闲分区
    private void mergeFreePartitions() {
        for (int i = partitions.size() - 1; i > 0; i--) {
            Partition prev = partitions.get(i - 1);
            Partition curr = partitions.get(i);
            if (prev.isFree && curr.isFree) {
                prev.size += curr.size;
                partitions.remove(i);
            }
        }
    }

    // 获取当前分区状态（字符串格式）
    private String getPartitionStatus() {
        StringBuilder sb = new StringBuilder();
        sb.append("起始地址\t大小\t状态\n");
        for (Partition p : partitions) {
            sb.append(p.start).append("KB\t\t")
                    .append(p.size).append("KB\t\t")
                    .append(p.isFree ? "空闲" : "已分配").append("\n");
        }
        return sb.toString();
    }
}